package com.example.demo.controller;

import com.example.demo.model.User;
import com.example.demo.service.UserService;
import com.example.demo.tools.Constant;
import com.example.demo.tools.ResponseBodyMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

// controller 负责关于用户的登录
@RestController
@RequestMapping("/user")
public class UserController {


    @Autowired
    private UserService userService;

    @RequestMapping("/login2")
    public ResponseBodyMessage<User> login(@RequestParam String username, @RequestParam String password,
                                           HttpServletRequest request) {
        // 因为我们在mapper中定义的方法的参数是一个 User对象 我们需要将其包装一下
        User userLogin = new User();
        userLogin.setUsername(username);
        userLogin.setPassword(password);
        User user = userService.login(userLogin);
        // 对查询的结果进行判断
        if (user == null) {
            // 登录失败
            System.out.println("登录失败");
            // 状态码为负数表示失败 message是错误信息 userLogin是 用户的信息
            return new ResponseBodyMessage<>(-1, "登录失败", userLogin);
        } else {
            // 登录成功
            System.out.println("登录成功");
            // 之后 我们还需要创建一个会话 这样下次用户自来访问的时候 就不用再登录了 所以我们要接收到request
            HttpSession session = request.getSession(true);
            user.setPassword("");
//            session.setAttribute("USERINFO_SESSION_KEY",user);
//            session.setAttribute意思是
//            用于将属性存储到 HttpSession 对象中。这里将一个名为 "USERINFO_SESSION_KEY"
//            的属性存储到 HttpSession 中，并将它的值设置为变量 user。
//            可以将USERINFO_SESSION_KEY理解为会话的属性名  但是有个问题 会话名太长了下次如果使用的话 可能会写错
//            所以我们 直接将其交给一个类(类似枚举类)管理 并且直接设置成常量 在包tools下 Constant
            session.setAttribute(Constant.USERINFO_SESSION_KEY, user);
            // 为了防止密码泄露
            userLogin.setPassword("");
            return new ResponseBodyMessage<>(0, "登录成功", userLogin);

        }
    }


    //    这样登录也有问题 就是别人可以通过抓包 来获取我们Request的信息 这样也能知道我们的密码
//    所以 我们使用BCrypt加密原理  MD5加密  我们要添加md5依赖 我们来模拟MD5加密
//    下面还是主要使用BCrypt加密 也是需要添加依赖的
//    引入BCrypt加密的属性成员
//    BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();//也可以通过属性注入的方式来引用

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;
    // 这样我们就可以通过属性注入的方式来实现引用BCrypt 这样的好处是 我们不用再去管他什么时候会去创建 直接就可以使用 实现代码解耦合
    @RequestMapping("/login")
    public ResponseBodyMessage<User> login2(@RequestParam String username, @RequestParam String password,
                                            HttpServletRequest request) {
        // 根据前端传递的用户名username 来查询对应的用户信息
        User user = userService.selectByName(username);

        // 对查询的结果进行判断
        if (user == null) {
            // 登录失败
            System.out.println("登录失败");
            // 状态码为负数表示失败 message是错误信息 userLogin是 用户的信息
            return new ResponseBodyMessage<>(-1, "登录失败", user);
        } else {
            // 登录成功
            System.out.println("登录成功");
            // 判断密码是否和前端的数据是一致的
            boolean flag = bCryptPasswordEncoder.matches(password, user.getPassword());
            if (flag) {//匹配成功
                // 之后 我们还需要创建一个会话 这样下次用户自来访问的时候 就不用再登录了 所以我们要接收到request
                HttpSession session = request.getSession(true);
                user.setPassword("");
                session.setAttribute(Constant.USERINFO_SESSION_KEY, user);
                return new ResponseBodyMessage<>(0, "登录成功", user);
            }
            // 匹配失败 就不会执行if语句
            // 为了防止密码泄露
            user.setPassword("");
            return new ResponseBodyMessage<>(-2, "登录失败", user);
        }
    }
}
